<template>
  <GenerateForm
    v-if="startParser"
    ref="generateFormRef"
    :form-conf="formConf"
    :form-data="formData"
    @submit="submitForm"
  />
</template>

<script lang="ts" name="BizProjectForm" setup>
import { computed, onMounted, onUnmounted, provide, ref } from "vue";
import UAParser from "ua-parser-js";
import { cloneDeep, get, keys, set } from "lodash-es";
import { useRoute } from "vue-router";
import dayjs from "dayjs";
import { themeDefaultValues } from "@/views/formgen/utils/theme";
import { parserFormLogic } from "./FormLogic";
import { dbDataConvertForItemJson } from "../../utils/convert";
import request from "@/utils/request";
import { htmlDecodeByRegExp, isMobile, loadCSS, removeHtmlTag } from "../../utils";
import { composeComponents } from "@/views/formgen/components/GenerateForm/config";
import { SubmitFormData } from "@/api/project/data";
import { FormConfigType, FormThemeType, getDefaultFormConfig } from "@/views/formgen/components/GenerateForm/types/form";
import GenerateForm from "../GenerateForm/index.vue";
import { getStaticBaseUrl } from "@/utils/auth";
import {
  FORM_PUBLIC_SETTING_KEY,
  FORM_THEME_KEY,
  IS_MOBILE_TAG_KEY,
  USER_FORM_STATE_KEY
} from "@/views/formgen/components/GenerateForm/types/constants";
import { getUserActiveTime } from "@/views/formgen/utils/usertime";
import { getFormDefaultLang, parseLangContent, setFormLangContent } from "../../utils/formI18n";
import { useUserFormInject } from "@/views/formgen/components/GenerateForm/hooks/useUserFormInject";

const formConf = ref<FormConfigType>(getDefaultFormConfig());

const startParser = ref(false);

provide(
  FORM_THEME_KEY,
  computed(() => formConf.value.theme || themeDefaultValues)
);
provide(
  FORM_PUBLIC_SETTING_KEY,
  computed(() => formConf.value.setting || {})
);

// 判断是否是移动端
const isMobileFlag = computed(() => {
  console.log(formConf.value);
  return formConf.value.isMobile === null || formConf.value.isMobile === undefined ? isMobile() : formConf.value.isMobile;
});

provide(IS_MOBILE_TAG_KEY, isMobileFlag);

const emit = defineEmits(["submit", "completed", "cover"]);

const propsData = defineProps<{
  // 表单配置
  formConfig?: FormConfigType;
  // 表单数据
  formData?: Record<string, any>;
  // 数据 ID 用来做数据回显的时候能找到数据 比如随机抽题找到上次抽的题目
  formDataId?: number;
}>();

const route = useRoute();

const userFormStore = useUserFormInject();
provide(USER_FORM_STATE_KEY, userFormStore);

onMounted(async () => {
  // Retrieve form key and kind from props or route query
  if (propsData.formConfig?.formKey) {
    formConf.value.formKey = propsData.formConfig.formKey;
    if (propsData.formConfig.formKind) {
      formConf.value.formKind = propsData.formConfig.formKind;
    }
  } else if (route.query.key) {
    formConf.value.formKey = route.query.key as string;
    if (route.query.kind) {
      formConf.value.formKind = Number(route.query.kind);
    }
    formConf.value.formBtns = true;
  }

  formConf.value.setting = propsData.formConfig?.setting;
  // 合并
  formConf.value = Object.assign(formConf.value, propsData.formConfig);
  // 加载数据
  // 是模板还是用户自定义表单
  let url = `/user/form/details/${formConf.value.formKey}?formDataId=${propsData.formDataId || 0}`;
  if (formConf.value.formKind === 2) {
    url = `/form/template/details/${formConf.value.formKey}`;
  }

  // 请求表单详细数据
  request.get(url).then((res: any) => {
    if (res.data) {
      // 主题数据
      if (res.data.userFormTheme) {
        formConf.value.theme = res.data.userFormTheme;
        // 处理封面
        handleShowFormCover(res.data.userFormTheme);
        // 加载自定义css
        loadCSS(res.data.userFormTheme?.cssUrl, "form-theme-css");
      }

      let defaultLang = getFormDefaultLang(formConf.value.formKey, res.data.form?.localeConfig?.defaultLang);

      // 表单信息
      if (res.data.form) {
        formConf.value.title = res.data.form.name;
        document.title = htmlDecodeByRegExp(removeHtmlTag(res.data.form.name));
        formConf.value.description = res.data.form.description;
        if (defaultLang) {
          setFormLangContent(formConf.value, defaultLang, res.data.form?.langContent);
        }
        formConf.value.langContent = res.data.form?.langContent;
        formConf.value.formType = res.data.form.type;
        formConf.value.formKey = res.data.form.formKey;
        // 多语言处理
        userFormStore.setLocaleConfig(res.data.form.localeConfig);
        userFormStore.setCurrentLang(defaultLang);
      }

      // 处理表单问题项
      const fields = res.data.formItems.map((item: any) => {
        const fieldItem = dbDataConvertForItemJson(item);
        // 解析多语言
        if (defaultLang) {
          parseLangContent(fieldItem, defaultLang, fieldItem?.langContent);
        }
        return fieldItem;
      });

      // 加载数学公式样式
      loadCSS(getStaticBaseUrl() + "/katex/katex.min.css", "form-katex-css");

      // 是否有分页 处理分页数据
      pageShowHandle(fields);
      // 处理一页一题
      handleOnePerPage(fields);

      if (keys(formConf.value.perPageFields).length !== 0) {
        formConf.value.fields = get(formConf.value.perPageFields, 1);
        formConf.value.formBtns = false;
      } else {
        formConf.value.fields = fields;
      }

      // 处理逻辑表单
      formConf.value.logicRuleMap = parserFormLogic(res.data, fields);
      console.log("formConf.value.logicRuleMap:", formConf.value.logicRuleMap);
      startParser.value = true;

      // 题库抽题
      userFormStore.setRandomQuestionIds(res.data?.extractInfo?.randomQuestionIds, res.data?.extractInfo?.internalQuestionIds);

      // 获取路由的参数
      userFormStore.setExtractInfo(route.query);

      // 加载完成后触发 给上级页面完成一些操作
      emit("completed");
    }
  });

  if (isMobileFlag.value) {
    formConf.value.size = "large";
  }
});

onUnmounted(() => {
  // 移除加载的css 避免污染其他页面
  const link = document.getElementById("form-theme-css");
  if (link) {
    link.remove();
  }
});

const handleShowFormCover = (theme: FormThemeType) => {
  console.log(theme.enableCover);
  console.log(isMobileFlag.value);
  if (theme.enableCover && isMobileFlag.value) {
    emit("cover", theme);
  }
};

/**
 * 分页组件处理
 * @param allFields
 */
const pageShowHandle = (allFields: any[]) => {
  // 判断是否存在分页
  const index = allFields.findIndex(item => item.typeId === "PAGINATION");
  if (index < 0) {
    return;
  }

  let curr = 1;
  // 每页字段
  const perPageFields: Record<string, any[]> = {};
  // 存储全部分页组件的信息
  const pageFields: Record<string, any> = {};

  // 遍历所有字段 把不同页的组件归类到对象的同一个key下
  allFields.forEach(item => {
    let fields = get(perPageFields, curr);
    if (item.typeId === "PAGINATION") {
      set(pageFields, curr, item);
      // 判断当前页是否有组件 如果没有组件则认为是一个无效的分页组件，页数则不+1
      if (fields) {
        item.currPageNum = curr++;
      }
    } else {
      // 防止没获取到
      if (!fields) {
        fields = [];
      }
      fields.push(item);
      set(perPageFields, curr, fields);
    }
  });

  const len = keys(perPageFields).length;
  // 计算总页数 为每个分页控件绑定数据 并把分页控件添加到每页的控件数据末尾，
  // 并且为最后一页默认生成一个分页控件 否则不拖动将无法返回第一页
  keys(perPageFields).forEach((key: string) => {
    // 获取分页组件的定义
    const pageItem = get(pageFields, key);
    if (pageItem) {
      const fields = get(perPageFields, key);
      pageItem.totalPageNum = len;
      fields.push(pageItem);
      set(perPageFields, key, fields);
    }
    // 特殊处理最后一页 如果没有主动拖分页 则默认添加一个
    else {
      // 至少有一个分页组件 所以从1开始
      let defaultPageItem = cloneDeep(get(pageFields, 1));
      const fields = get(perPageFields, key);
      defaultPageItem.totalPageNum = len;
      defaultPageItem.currPageNum = len;
      fields.push(defaultPageItem);
      set(perPageFields, key, fields);
    }
  });
  formConf.value.perPageFields = perPageFields;
};

// 处理每页一题
const handleOnePerPage = (fields: any[]) => {
  // 如果只有一个题目
  if (fields.length && fields.length < 2) {
    return;
  }

  // 开启了每页一题
  if (!formConf.value.setting?.onePageOneQuestion?.enableOnePageOneQuestion) {
    return;
  }

  // 找到分页的数据
  const pageCom = composeComponents.find(item => item.typeId === "PAGINATION") as any;
  // 除了隐藏的组件 每页一题
  const perPageFields: Record<string, any[]> = {};
  let curr = 1;
  const allFields = fields.filter((item: any) => !item.hideType);
  // 找到隐藏的组件 通通放到第一页 不然用户组件默认值就失效了
  const hiddenFields = fields.filter((item: any) => item.hideType);

  allFields.forEach((item: any, index: number) => {
    const currentPageComs = [item];
    const tempPageCom = cloneDeep(pageCom);
    tempPageCom!.totalPageNum = allFields.length;
    tempPageCom!.currPageNum = curr;
    // 不允许返回上一页
    if (formConf.value.setting?.onePageOneQuestion?.hidePrevPageBtn) {
      tempPageCom!.prev = false;
    }
    tempPageCom!.vModel = `pagination${new Date().getTime() + index}`;
    if (index === 0) {
      currentPageComs.push(...hiddenFields);
    }
    currentPageComs.push(tempPageCom);
    set(perPageFields, curr, cloneDeep(currentPageComs));
    curr++;
  });
  formConf.value.perPageFields = perPageFields;
};

//  统计用户停留时间
const ua = new UAParser(navigator.userAgent);

const submitFormData = ref<SubmitFormData>({
  completeTime: 0,
  formKey: formConf.value.formKey,
  submitOs: ua.getOS()?.name,
  submitBrowser: ua.getBrowser()?.name,
  submitUa: ua.getResult(),
  wxUserInfo: null,
  wxOpenId: null,
  formType: formConf.value.formType || 1,
  otherParam: undefined,
  originalData: null
});

const beginTime = ref(dayjs());

const submitForm = (data: any) => {
  console.log("formmodel:", data);
  const { formModel } = data;
  const allData = {
    ...submitFormData.value,
    anonymous: formConf.value.setting?.anonymousWrite || false,
    completeTime: getUserActiveTime() || 0,
    originalData: formModel,
    formType: formConf.value.formType,
    beginTime: beginTime.value.format("YYYY-MM-DD HH:mm:ss")
  };
  emit("submit", allData);
};

const generateFormRef = ref<InstanceType<typeof GenerateForm> | null>(null);

defineExpose({
  submitForm,
  formConf,
  generateFormRef
});
</script>

<style lang="scss">
$themeColor: var(--form-theme-color);
@use "../../assets/styles/custom-theme-popper" as *;
</style>

<style lang="scss" scoped>
$themeColor: var(--form-theme-color);
@use "../../assets/styles/custom-theme" as *;
</style>
